﻿using EnvDTE;
using Sasa.QualityTools.CodeAnalysis.Core.VisualStudio;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics.CodeAnalysis;

namespace Sasa.QualityTools.CodeAnalysis.FxCopIntegrator.VisualStudio
{
    public abstract class CodeModel : ICodeModel
    {
        private static readonly string[] SupportedLanguage = 
        {
            CodeModelLanguageConstants.vsCMLanguageCSharp,
            CodeModelLanguageConstants.vsCMLanguageVB
        };


        protected FileCodeModel Model { get; private set; }

        public virtual bool IsSupportedLanguage
        {
            get
            {
                return true;
            }
        }

        public virtual IEnumerable<string> TypeNames
        {
            get
            {
                var typeNames = new List<string>();
                foreach (CodeElement element in Model.CodeElements)
                {
                    typeNames.AddRange(GetTypeNames(element, ""));
                }
                return typeNames;
            }
        }


        protected CodeModel(FileCodeModel model)
        {
            Model = model;
        }


        public static ICodeModel CreateInstance(FileCodeModel model)
        {
            ICodeModel result = new UnsupportedLanguageCodeModel(model);

            if (model != null)
            {
                switch (model.Language)
                {
                    case CodeModelLanguageConstants.vsCMLanguageCSharp:
                        result = new CSharpCodeModel(model);
                        break;
                    case CodeModelLanguageConstants.vsCMLanguageVB:
                        result = new VisualBasicCodeModel(model);
                        break;
                }
            }

            return result;
        }

        [SuppressMessage("Microsoft.Performance", "CA1800")]
        protected virtual IEnumerable<string> GetTypeNames(CodeElement element, string prefix)
        {
            var typeNames = new List<string>();

            if (element is CodeNamespace)
            {
                foreach (CodeElement child in ((CodeNamespace)element).Members)
                {
                    typeNames.AddRange(GetTypeNames(child, prefix + ((CodeNamespace)element).Name + "."));
                }
            }
            else if (element is CodeType)
            {
                var typeName = ConvertToClrTypeName(element.FullName.Substring(element.FullName.LastIndexOf('.') + 1));
                typeNames.Add(prefix + typeName);
                foreach (CodeElement child in ((CodeType)element).Members)
                {
                    typeNames.AddRange(GetTypeNames(child, prefix + typeName + "+"));
                }
            }

            return typeNames;
        }

        protected virtual string ConvertToClrTypeName(string typeName)
        {
            return typeName;
        }
    }
}
